package com.hzw.saas.service.product.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import javax.annotation.Resource;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hzw.saas.api.product.IItemOrderService;
import com.hzw.saas.api.product.IPaymentOfflineService;
import com.hzw.saas.api.product.IPaymentOnlineService;
import com.hzw.saas.api.product.dto.ItemOrderDto;
import com.hzw.saas.api.product.dto.ItemOrderInfoDto;
import com.hzw.saas.api.product.dto.PaymentOfflineDto;
import com.hzw.saas.api.product.dto.PaymentOnlineDto;
import com.hzw.saas.api.product.enums.OrderStatus;
import com.hzw.saas.api.product.enums.OrderType;
import com.hzw.saas.api.product.enums.PayMode;
import com.hzw.saas.common.config.exception.DefaultSaasException;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.config.util.PageUtils;
import com.hzw.saas.common.pay.enums.PayType;
import com.hzw.saas.common.util.IdWorker;
import com.hzw.saas.service.product.mapper.ItemOrderMapper;
import com.hzw.saas.service.product.model.ItemOrder;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author zzl
 * @since 2021-01-21
 */
@Slf4j
@Service("itemOrderServiceImpl")
@RequiredArgsConstructor
public class ItemOrderServiceImpl extends ServiceImpl<ItemOrderMapper, ItemOrder> implements IItemOrderService,
    IService<ItemOrder> {

    private final IdWorker idWorker;
    private final MapperFacade mapperFacade;
    @Resource(name = "paymentOnlineServiceImpl")
    private IPaymentOnlineService paymentOnlineService;
    @Resource(name = "paymentOfflineServiceImpl")
    private IPaymentOfflineService paymentOfflineService;

    @Override
    public ItemOrderDto get(String orderId) {
        if (StringUtils.isBlank(orderId)) {
            return null;
        }
        ItemOrder itemOrder = this.getById(orderId);
        return mapperFacade.map(itemOrder, ItemOrderDto.class);
    }

    @Override
    public ItemOrderInfoDto getInfo(String orderId) {
        if (StringUtils.isBlank(orderId)) {
            return null;
        }
        ItemOrderDto itemOrderDto = get(orderId);
        if (itemOrderDto == null) {
            return null;
        }
        return this.getInfo(itemOrderDto);
    }

    @Override
    public IPage<ItemOrderDto> list(PageParam pageParam, ItemOrderDto cnd) {
        ItemOrder entity = mapperFacade.map(cnd, ItemOrder.class);
        IPage<ItemOrder> page = this.page(pageParam.convert(), Wrappers.<ItemOrder>query().setEntity(entity));
        return PageUtils.convert(page, ItemOrderDto.class);
    }

    @Override
    public IPage<ItemOrderInfoDto> listInfo(PageParam pageParam, ItemOrderDto cnd) {
        List<ItemOrderInfoDto> orderInfoList = new ArrayList<>();
        IPage<ItemOrderDto> list = this.list(pageParam, cnd);
        for (ItemOrderDto itemOrderDto : list.getRecords()) {
            ItemOrderInfoDto itemOrderInfoDto = this.getInfo(itemOrderDto);
            orderInfoList.add(itemOrderInfoDto);
        }
        IPage<ItemOrderInfoDto> result = new Page<>(list.getCurrent(), list.getSize(), list.getTotal());
        result.setRecords(orderInfoList);
        return result;
    }

    @Override
    public ItemOrderDto add(ItemOrderDto itemOrderDto) {
        if (StringUtils.isBlank(itemOrderDto.getOrderId())) {
            itemOrderDto.setOrderId(String.valueOf(idWorker.nextId()));
        }
        if (itemOrderDto.getCreateTime() == null) {
            itemOrderDto.setCreateTime(new Date());
        }

        ItemOrder itemOrder = mapperFacade.map(itemOrderDto, ItemOrder.class);
        this.save(itemOrder);
        return itemOrderDto;
    }

    @Override
    public boolean update(ItemOrderDto itemOrderDto) {
        if (StringUtils.isBlank(itemOrderDto.getOrderId())) {
            throw DefaultSaasException.build("order id is blank").status(HttpStatus.BAD_REQUEST);
        }
        return this.updateById(mapperFacade.map(itemOrderDto, ItemOrder.class));
    }

//    @Override
//    @Transactional
//    public ItemOrderDto createOfflineItemOrder(ItemOrderDto itemOrderDto) {
//        /** 构造订单数据*/
//        itemOrderDto.setFinallyTime(new Date());
//        itemOrderDto.setPayTime(new Date());
//        itemOrderDto.setItemPriceDiscount(0d);
//        itemOrderDto.setPayMode(PayMode.OFFLINE_PAY.value());
//        itemOrderDto.setPayModeText(PayMode.OFFLINE_PAY.text());
//        itemOrderDto.setStatus(OrderStatus.PAY_SUCCESS.value());
//        itemOrderDto.setStatusText(OrderStatus.PAY_SUCCESS.text());
//        itemOrderDto.setItemId("-1");
//        itemOrderDto.setIsPayed(1);
//
//        /** 验证用户是否存在*/
//        UserAccountBO userAccountBO =
//            userAccountService.getAccount(new UserAccountGetQuery().setUserId(itemOrderDto.getUserId()));
//        AssertUtil.assertThrow("创建订单失败，指定的用户不存在", Objects.isNull(userAccountBO));
//
//        /**  验证超算是否存在*/
//        String hpcId = itemOrderDto.getHpcId();
//        HpcConfigBo hpcConfigDto = hpcConfigService.get(hpcId);
//        AssertUtil.assertThrow("创建订单失败，指定的超算中心不存在", Objects.isNull(hpcConfigDto));
//
//        String hpcAccountId = itemOrderDto.getPid();
//        if (StringUtil.isNotBlank(hpcAccountId)) {
//            /** 续费超算账号*/
//            try {
//                hpcAccountUserService.tagHpcAccount(hpcAccountId);
//            } catch (DefaultSaasException e) {
//                throw DefaultSaasException.build("创建订单失败，" + e.getMessage(), e);
//            }
//        }
//        itemOrderDto = itemOrderService.add(itemOrderDto);
//        /** 添加支付信息*/
//        addPaymentOffLineInfo(itemOrderDto.getOrderId(), itemOrderDto.getUserId(), OrderType.ITEM,
//            itemOrderDto.getItemPrice());
//
//        return itemOrderDto;
//    }
//
//    @Override
//    @Transactional
//    @RedisLock(lockName = "OrderItemConfirm", key = "#orderId")
//    public void orderItemConfirm(String orderId, String userId) {
//        ItemOrderDto itemOrderDto = itemOrderService.get(orderId);
//        AssertUtil.assertThrow("确认订单失败，订单不存在", Objects.isNull(itemOrderDto));
//        OrderStatus orderStatus = OrderStatus.instance(itemOrderDto.getStatus());
//        // 重复确认
//        if (OrderStatus.CONFIRM_SUCCESS == orderStatus) {
//            return;
//        }
//
//        if (OrderStatus.PAY_SUCCESS != orderStatus && OrderStatus.CONFIRM_FAIL != orderStatus) {
//            log.error("确认订单{}失败，订单状态异常(:{})", orderId, orderStatus.text());
//            AssertUtil.assertThrow(String.format("确认订单失败，订单状态异常(:%d)", orderStatus.value()), true);
//        }
//
//        /** 更新线下支付表*/
//        Integer value = itemOrderDto.getPayMode();
//        PayMode payMode = PayMode.instance(value);
//        switch (payMode) {
//            case OFFLINE_PAY:
//                // 线下
//                PaymentOfflineDto paymentOfflineDto = paymentOfflineService.getByOrder(orderId);
//                AssertUtil.assertThrow("确认订单失败，支付信息丢失", Objects.isNull(paymentOfflineDto));
//                paymentOfflineDto.setAdminId(userId);
//                paymentOfflineDto.setPayStatus(OrderStatus.CONFIRM_SUCCESS.value());
//                paymentOfflineService.update(paymentOfflineDto);
//                break;
//            case ONLINE_PAY:
//                // 线上
//                PaymentOnlineDto paymentOnlineDto = paymentOnlineService.getByOrder(orderId);
//                AssertUtil.assertThrow("确认订单失败，支付信息丢失", Objects.isNull(paymentOnlineDto));
//                // paymentOnlineDto.setAdminId(userId);
//                paymentOnlineDto.setPayStatus(OrderStatus.CONFIRM_SUCCESS.value());
//                paymentOnlineService.update(paymentOnlineDto);
//                break;
//        }
//
//        String hpcAccountId = itemOrderDto.getPid();
//        if (StringUtil.isBlank(hpcAccountId)) {
//            HpcAccountRecordBo accountUserBo = new HpcAccountRecordBo();
//            accountUserBo.setUserId(itemOrderDto.getUserId())
//                .setRegisterDate(DateUtil.date())
//                .setCoreTimeBalance(itemOrderDto.getItemCoreTime())
//                .setCoreTimeBalanceTotal(itemOrderDto.getItemCoreTime())
//                .setExpireDate(DateUnit.fromNowON(itemOrderDto.getItemDatePeriod(), itemOrderDto.getItemDateUnit()))
//                .setStatus(HpcAccountStatus.NORMAL.value());
//
//            /** 创建订单时没有选择超算账号，从账号池中随机取一个账号进行绑定*/
//            // 保证并发情况下取到的超算账号不一致的
//            HpcAccountBo hpcAccountPoolBo = hpcAccountUserService.autoBoundHpcAccountPool(orderId, accountUserBo,
//                itemOrderDto.getHpcId());
//
//            if (Objects.isNull(hpcAccountPoolBo)) {
//                log.error("确认订单{}失败，超算账号余量不足，请导入超算账号数据", orderId);
//                AssertUtil.assertThrow(String.format("确认订单失败，超算账号余量不足，请导入超算账号数据", orderStatus.value()), true);
//            }
//        } else {
//            Double itemCoreTime = itemOrderDto.getItemCoreTime(); // 核时
//            Integer itemDatePeriod = itemOrderDto.getItemDatePeriod(); // 有效数值
//            String itemDateUnit = itemOrderDto.getItemDateUnit(); // 有效单位
//            hpcAccountUserService.renewHpcAccount(orderId, hpcAccountId, itemCoreTime, itemDatePeriod, DateUnit.instance(itemDateUnit));
//        }
//    }


    private ItemOrderInfoDto getInfo(ItemOrderDto itemOrderDto) {
        ItemOrderInfoDto itemOrderInfoDto = new ItemOrderInfoDto();
        itemOrderInfoDto.setOrder(itemOrderDto);
        itemOrderDto.setPayModeText(PayMode.text(itemOrderDto.getPayMode()));
        itemOrderDto.setStatusText(OrderStatus.text(itemOrderDto.getStatus()));

        if (Objects.equals(itemOrderDto.getPayMode(), PayMode.ONLINE_PAY.value())) {
            PaymentOnlineDto paymentOnlineDto = paymentOnlineService.getByOrder(itemOrderDto.getOrderId());
            paymentOnlineDto.setPayTypeText(PayType.text(paymentOnlineDto.getPayType()));
            paymentOnlineDto.setPayStatusText(OrderStatus.text(paymentOnlineDto.getPayStatus()));
            itemOrderInfoDto.setPaymentOnline(paymentOnlineDto);
        } else if (Objects.equals(itemOrderDto.getPayMode(), PayMode.OFFLINE_PAY.value())) {
            PaymentOfflineDto paymentOfflineDto = paymentOfflineService.getByOrder(itemOrderDto.getOrderId());
            if (Objects.isNull(paymentOfflineDto)) return itemOrderInfoDto;
            paymentOfflineDto.setPayStatusText(OrderStatus.text(paymentOfflineDto.getPayStatus()));
            itemOrderInfoDto.setPaymentOffline(paymentOfflineDto);
        }
        return itemOrderInfoDto;
    }

    private void addPaymentOffLineInfo(String orderId, String userId, OrderType orderType, Double payAmount) {
        PaymentOfflineDto paymentOfflineQuery = new PaymentOfflineDto();
        paymentOfflineQuery.setOrderId(orderId);
        paymentOfflineQuery.setPayId(String.valueOf(idWorker.nextId()));
        paymentOfflineQuery.setCreateTime(new Date());
        paymentOfflineQuery.setPayStatus(-1);
        paymentOfflineQuery.setPayStatus(orderType.value());
        if (payAmount == null) {
            paymentOfflineQuery.setPayAmount(-1d);
        } else {
            paymentOfflineQuery.setPayAmount(payAmount);
        }
        paymentOfflineQuery.setUserId(userId);
        paymentOfflineQuery.setFlowId("-1");
        paymentOfflineQuery.setPayStatus(OrderStatus.PAY_SUCCESS.value());
        paymentOfflineQuery.setPayTime(new Date());
        paymentOfflineQuery.setOrderType(orderType.value());
        paymentOfflineService.add(paymentOfflineQuery);
    }

}
